/*
 * Users_MemManage.c
 *
 *  Created on: Aug 8, 2020
 *      Author: MrWang
 */

/*
 * 使用内存池进行内存管理
 * 建立多个不同大小的内存值,外部申请分配内存时,根据申请的内存大小选择使用的内存池,然后分配内存,如果对应的内存池没有空余内存块
 * 则尝试向更大一点的内存池申请内存,依次处理,如果最大的内存池也没用空间,那将返回错误.
 * 通过使用内存池,可以提高内存分配的速度以及尽量防止出现内存碎片,提高系统稳定性.
 * */
#include "Users_MemManage.h"

#include <rtdef.h>

#ifdef RT_USING_MEMPOOL
/*
 * 内存池中每块的大小和个数
 * 内存池块个数 = pool_size/(block_size + 4),其中4为链表指针大小
 * 要注意,定义内存池大小的时候要注意和整个系统中需要频繁使用内存池的需求大小相匹配,这样提高内存使用率
 * !!!!!!!
 * 注意为了提高效率,定义内存池的大小必须是4字节的整数倍.并且要求必须对齐.
 * !!!!!!!
 *
 * */

#define MemPool_F_Block_Size			(8)
#define MemPool_F_Num					(150)
#define MemPool_F_Pool_Size				(MemPool_F_Num * (MemPool_F_Block_Size + 4))

#define MemPool_A_Block_Size			(40)
#define MemPool_A_Num					(120)
#define MemPool_A_Pool_Size				(MemPool_A_Num * (MemPool_A_Block_Size + 4))

#define MemPool_B_Block_Size			(128)
#define MemPool_B_Num					(10)
#define MemPool_B_Pool_Size				(MemPool_B_Num * (MemPool_B_Block_Size + 4))

#define MemPool_C_Block_Size			(256)
#define MemPool_C_Num					(4)
#define MemPool_C_Pool_Size				(MemPool_C_Num * (MemPool_C_Block_Size + 4))

#define MemPool_D_Block_Size			(512)
#define MemPool_D_Num					(2)
#define MemPool_D_Pool_Size				(MemPool_D_Num * (MemPool_D_Block_Size + 4))

#define MemPool_E_Block_Size			(1024)
#define MemPool_E_Num					(1)
#define MemPool_E_Pool_Size				(MemPool_E_Num * (MemPool_E_Block_Size + 4))

ALIGN(4) static struct rt_mempool  MemPool_F;
ALIGN(4) static struct rt_mempool  MemPool_A;
ALIGN(4) static struct rt_mempool  MemPool_B;
ALIGN(4) static struct rt_mempool  MemPool_C;
ALIGN(4) static struct rt_mempool  MemPool_D;
ALIGN(4) static struct rt_mempool  MemPool_E;

//为了提高效率一定要对齐
ALIGN(4) static uint8_t data_MemPool_F[MemPool_F_Pool_Size];
ALIGN(4) static uint8_t data_MemPool_A[MemPool_A_Pool_Size];
ALIGN(4) static uint8_t data_MemPool_B[MemPool_B_Pool_Size];
ALIGN(4) static uint8_t data_MemPool_C[MemPool_C_Pool_Size];
ALIGN(4) static uint8_t data_MemPool_D[MemPool_D_Pool_Size];
ALIGN(4) static uint8_t data_MemPool_E[MemPool_E_Pool_Size];

/****************************************************************************
* 函数：
* 功能：初始化内存池
* 参数：
* 备注：
*****************************************************************************/
#define Init_Mempool(NAME)		\
	do{\
		ret = rt_mp_init(&MemPool_##NAME, "MemPool"#NAME, data_MemPool_##NAME, sizeof(data_MemPool_##NAME), MemPool_##NAME##_Block_Size);\
		if(ret != RT_EOK){\
			goto EndThisFun;\
		}\
	}while(0)

/****************************************************************************
* 函数：
* 功能：初始化内存池
* 参数：
* 备注：
*****************************************************************************/
void Users_Mem_Init(void)
{
	rt_err_t ret = RT_EOK;

	Init_Mempool(F);
	Init_Mempool(A);
	Init_Mempool(B);
	Init_Mempool(C);
	Init_Mempool(D);
	Init_Mempool(E);

	EndThisFun:
	if(ret != RT_EOK){
		while(1){
			rt_thread_delay(1000);
		}
	}
}

/****************************************************************************
* 函数：
* 功能：分配内存成功后返回内存
* 参数：
* 备注：失败后会尝试申请更大块的内存
*****************************************************************************/
#define Users_MP_Alloc(NAME)	\
	do{\
		if(len <= MemPool_##NAME##_Block_Size){\
			ret = rt_mp_alloc(&MemPool_##NAME, 0);\
			if(ret != NULL){\
				return ret;\
			}\
		}\
	}while(0)

/****************************************************************************
* 函数：
* 功能：分配地址
* 参数：
* 备注：
*****************************************************************************/
void* Users_Malloc(uint32_t len)
{
	uint8_t* ret = NULL;

	Users_MP_Alloc(F);
	Users_MP_Alloc(A);
	Users_MP_Alloc(B);
	Users_MP_Alloc(C);
	Users_MP_Alloc(D);
	Users_MP_Alloc(E);

	return ret;
}

#endif
